package com.sky.service.impl;

import com.sky.context.BaseContext;
import com.sky.dto.ShoppingCartDTO;
import com.sky.entity.Dish;
import com.sky.entity.Setmeal;
import com.sky.entity.ShoppingCart;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.service.ShoppingCartService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @author DragonflyYue
 */
@Service
@Slf4j
public class ShoppingCartServiceImpl implements ShoppingCartService {

    @Autowired
    private ShoppingCartMapper shoppingCartMapper;

    @Autowired
    private DishMapper dishMapper;
    
    @Autowired
    private SetmealMapper setmealMapper;
    

    /**
     * 添加购物车
     * 不同的用户要有自己的购物车,所以要通过user_id来区分
     * @param shoppingCartDTO
     */
    @Override
    public void addShoppingCart(ShoppingCartDTO shoppingCartDTO) {

        //1.判断当前加入到购物车中的商品是否已经存在了
            //写成动态sql,因为会涉及到多个条件

        ShoppingCart shoppingCart = new ShoppingCart();
        //属性拷贝
        BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);
        //因为这个 ShoppingCartDTO中并没有对应的userId
            //每次用户端发送请求的时候,都会把对应的token携带过来,
            // 而前面我们定义过拦截器JwtTokenUserInterceptor,这个是用户端的拦截器,
                // 在sky-server/interceptor目录下
            //在拦截器中,通过ThreadLocal提供的方法,把token存到了BaseContext(线程的临时空间中),
            //因此,,我们可以直接通过BaseContext直接获取这个userId

        //拿到当前微信用户的id(因为购物车,应该是每个用户有单独的购物车对应的数据项)
        Long userId = BaseContext.getCurrentId();
        //放入到shoppingCart中,此时所需要传的参数,userId,dishId,setmealId,dishFlavor就都有了
            //后面的三个参数,就是上面属性拷贝放入的
        shoppingCart.setUserId(userId);
        //这里为啥要传入shoppingCart对象,为啥不直接传入ShoppingCartDTO对象,因为DTO中没有userId属性,
            //而我们无法直接获取到对应的用户id,得需要线程临时存储空间BaseContext中调用
        List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);

        //2.如果已经存在了,就只需要对表中的number字段(商品数量)  +1,就可以了,不用再insert一条数据了

        if (list != null && list.size() > 0){

            //虽然上面我们写的list方法返回的是多个购物车对象,但是我们可以想,当前用户id的购物车,那肯定是唯一的呀
                //所以我们取出的第一条数据,也可以理解为唯一的一条数据;;
                //自己理解: 那上面list方法还返回List集合就不是很贴切,直接返回一个ShoppingCart对象就可以了
            ShoppingCart cart = list.get(0);
            //修改菜品数量
            cart.setNumber(cart.getNumber() + 1);
            //下面要把这个对应的菜品数量,通过update语句更新数据库
                //update shopping_cart set number = ? where id = ?
                // 上面这里的id指的是shoppingCart对象中的id,那就是购物车id
            shoppingCartMapper.updateNumberById(cart);
            //单纯看上面逻辑,也挺麻烦的也要操作数据库;;但是如果直接像下面直接插入数据,那要修改的就太多了,
                // 所有数据要都查出来,然后里面所有的属性都要赋值,然后插入,,因为是新建信息,所以各个属性都要有值,,
                //那这样分析,就还是updateNumber,操作的数据库更少
        }else {

        //3.如果不存在,需要插入一条购物车数据

            //可以直接使用上面的shoppingCart对象,但是属性值还不够; 因为这里是新插入菜品数据
                //可是前端传过来的shoppingCartDTO并没有传过来这些数据,,因此需要我们单独查询

            //3.1 需要先判断,传来的到底是菜品,还是一个套餐,
                // 因为对应的相关信息(如name,图片路径等等),都要去对应的dish表还是setmeal表查询

            //获取对应的dishId,可以用来查询dish表中的菜品信息
            Long dishId = shoppingCartDTO.getDishId();

            //3.2 判断当前添加到购物车的是菜品还是套餐
                //首先,当前购物车一肯定没数据,我们要插入数据,所以只要能判断 菜品和套餐谁不为null,
                // 那当前插入的就是什么数据,比如是菜品数据,就可以去dish表把对应的菜品信息查出来

            if (dishId != null){
                //本次添加到购物车的是菜品数据
                    //每次只能新添加一种,不可能同时又添加菜品,又添加套餐
                
                Dish dish = dishMapper.getById(dishId);
                //将对应的数据添加到,shoppingCart对象中(还name,image,amount,)
                shoppingCart.setName(dish.getName());
                shoppingCart.setImage(dish.getImage());
                //这里需要注意,shoppingCart中用的价格是amount,而dish中是用的price
                shoppingCart.setAmount(dish.getPrice());  
                
               ////下面公共部分,就提到if-else外面去了
               // shoppingCart.setNumber(1);  //这里是新增菜品/套餐信息,,所以这新增的数量可以设置成1
               // shoppingCart.setCreateTime(LocalDateTime.now());
               // //不过话说上面这个当前时间,不用公共类填充吗?不过自动填充@AutoFill是在mapper层使用的
            }else{
                //此时说明添加的是套餐
                
                //获取对应的setmealId,用来查询setmeal表中对应的套餐信息
                Long setmealId = shoppingCartDTO.getSetmealId();

                Setmeal setmeal = setmealMapper.getById(setmealId);

                //将对应的数据添加到,shoppingCart对象中(还name,image,amount,)
                shoppingCart.setName(setmeal.getName());
                shoppingCart.setImage(setmeal.getImage());
                //这里需要注意,shoppingCart中用的价格是amount,而setmeal中是用的price
                shoppingCart.setAmount(setmeal.getPrice());
                //shoppingCart.setNumber(1);  //这里是新增菜品/套餐信息,,所以这新增的数量可以设置成1
                //shoppingCart.setCreateTime(LocalDateTime.now());
            }
            //因为下面两行的设置,无论是dish里面,还是setmeal中都要设置,代码一样,,所以就单独提出来了
            shoppingCart.setNumber(1);  //这里是新增菜品/套餐信息,,所以这新增的数量可以设置成1
            shoppingCart.setCreateTime(LocalDateTime.now());
            //不过话说上面这个当前时间,不用公共类填充吗?不过自动填充@AutoFill是在mapper层使用的
            
            //统一插入数据到数据库
                //上面的if-else用来封装对应的shoppingCart对象里面的数据,,
                //添加的是菜品,就把对应的dish信息放入到shoppingCart对象; 套餐同理,,最终执行插入sql语句
            shoppingCartMapper.insert(shoppingCart);
        }
    }

    /**
     * 查看购物车
     * @return
     */
    @Override
    public List<ShoppingCart> showShoppingCart() {
        //获取到当前微信用户的id
        Long userId = BaseContext.getCurrentId();
        //因为下面list要传的是shoppingCart对象,所以要单独创建一个这个对象
        ShoppingCart shoppingCart = ShoppingCart.builder()
                .userId(userId)
                .build();   //这个属性也比较少,,所以自己new个,然后setUserId感觉也可以

        List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
        
        return list;
    }

    /**
     * 清空购物车
     */
    @Override
    public void cleanShoppingCart() {

        //获取到当前微信用户的id
        Long userId = BaseContext.getCurrentId();
        
        shoppingCartMapper.deleteByUserId(userId);
        
    }

    /**
     * 删除购物车中的一个商品
     * @param shoppingCartDTO
     */
    @Override
    public void subShoppingCart(ShoppingCartDTO shoppingCartDTO) {
        
        ShoppingCart shoppingCart = new ShoppingCart();
        BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);
        //查询购物车中的菜品信息
        List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
        
        if (list != null && list.size() > 0){
            shoppingCart = list.get(0);

            Integer number = shoppingCart.getNumber();
            if (number == 1){   //这里我没考虑到
                //如果数量为1,那这里减少数量就相当于删除对应菜品
                shoppingCartMapper.deleteById(shoppingCart.getId());
                //上面这里为啥不直接通过删除用户id来删除对应菜品,
                    //首先你购物车id,可以标识当前菜品,那只要菜品属性更改,就是独立的一条购物车数据;
                    // 如果是删除用户id,那你购物车中所有数据都会被删除;所以前面的清空购物车,,是用用户id来删除的

            }else{
                //如果数量不为1,那说明,此时减少菜品就是一个update,修改对应的number就行
                number = number -1;
                shoppingCart.setNumber(number);
                shoppingCartMapper.updateNumberById(shoppingCart);
            }
        }
    }
}
